/**
 * 
 */
package juegos;

import java.util.Vector;



/**
 * Para este juego no se puede usar la busqueda bidireccional, no es lo mismo verter que "desverter"
 * 
 * @author DaNieLooP
 *
 */
public class NodoGarrafas extends Nodo{
	/**
	 * garrafa de 4 litros
	 */
	private int g4;
	/**
	 * garrafa de 3 litros
	 */
	private int g3;
	
	/**
	 * constructora de clase
	 */
	public NodoGarrafas(){
		this.informado=false;
		this.camino="Estado inicial, ";
		this.coste = 0;
		this.g3=0;
		this.g4=0;
		this.profundidad=0;
		this.vHeur=-1;
		this.calculaEstado();
	}
	/**
	 * constructora con parametros
	 * @param ga4 garrafa de 4 litros
	 * @param ga3 garrafa de 3 litros
	 * @param op operador a usar
	 * @param c camino hasta el nodo
	 * @param costeCamino coste del camino c
	 * @param profundidad profundidad de este nodo
	 */
	public NodoGarrafas(int ga4,int ga3,int op,String c, int costeCamino, int profundidad){
		this.informado=false;
		this.g4 = ga4;
		this.g3 = ga3;
		this.coste = costeCamino+1;
		this.profundidad = profundidad+1;
		this.vHeur = -1;
		this.calculaEstado();
		String mov;
		switch (op){
		case 1: mov = (" Llena 4,"); break;
		case 2: mov = (" Llena 3,"); break;
		case 3: mov = (" Vacia 4,"); break;
		case 4: mov = (" Vacia 3,"); break;
		case 5: mov = (" Vierte 4 a 3,"); break;
		case 6: mov = (" Vierte 3 a 4,"); break;
		default: mov = ("No existe ese movimiento");
		}
		this.camino = (c + mov);
	}
	
	/**
	 * Establecer el estado final
	 */
	public void setFinal(){
		this.g3=0;
		this.g4=2;
		this.coste = 0;
		this.profundidad = 0;
		this.vHeur = -1;
		this.camino = "Desde estado final->";
		this.calculaEstado();
	}
	
	/**
	 * operador que llena la garrafa de 4 litros del grifo.
	 * @return nuevo nodo con la garrafa de 4 llena
	 */
	private NodoGarrafas llena4(){
		NodoGarrafas nuevo=null;
		if (g4<4){
			nuevo=new NodoGarrafas(4,g3,1,this.camino,this.coste,this.profundidad);
		}
		return nuevo;
	}
	/**
	 * operador que llena la garrafa de 3 litros
	 * @return nuevo nodo con la garrafa de 3 llena
	 */
	private NodoGarrafas llena3(){
		NodoGarrafas nuevo=null;
		if (g3<3){
			nuevo=new NodoGarrafas(g4,3,2,this.camino,this.coste,this.profundidad);
		}
		return nuevo;
	}
	/**
	 * Operador que vacia la garrafa de 4 litros
	 * @return nuevo nodo con la garrafa de 4 vacia
	 */
	private NodoGarrafas vacia4(){
		NodoGarrafas nuevo=null;
		if(g4>0){
			nuevo=new NodoGarrafas(0,g3,3,this.camino,this.coste,this.profundidad);
		}
		return nuevo;
	}
	/**
	 * Operador que vacia la garrafa de 3 litros
	 * @return nuevo nodo con la garrafa de 3 vacia
	 */
	private NodoGarrafas vacia3(){
		NodoGarrafas nuevo=null;
		if(g3>0){
			nuevo=new NodoGarrafas(g4,0,4,this.camino,this.coste,this.profundidad);
		}
		return nuevo;
	}
	/**
	 * Echa el contenido de la garrafa de 4 en la de 3 litros
	 * @return nuevo nodo 
	 */
	private NodoGarrafas vierte4(){
		NodoGarrafas nuevo=null;
		if (g4>0&g3<3){
			int y;
			if (3<g4+g3) y=3;
			else y=g4+g3;
			int x=g4-(y-g3);
			nuevo=new NodoGarrafas(x,y,5,this.camino,this.coste,this.profundidad);
		}
		return nuevo;
	}
	/**
	 * Echa el contenido de la de 3 en la de 4 litros
	 * @return nuevo nodo
	 */
	
	private NodoGarrafas vierte3(){
		NodoGarrafas nuevo=null;
		if(g4<4&g3>0){
			int x;
			if (4<g3+g4) x=4;
			else x=g3+g4;
			int y=g3-(x-g4);
			nuevo=new NodoGarrafas(x,y,6,this.camino,this.coste,this.profundidad);
			return nuevo;
		}
		return nuevo;
	}
	/**
	 * Asigna al estado un valor
	 */
	public void calculaEstado(){
		this.estado = this.g4*100+this.g3;
	}
	/**
	 * Como este juego no tiene heuristica la ponemos a -1
	 */
	public void calculaHeur(){
		this.vHeur = -1;
	}
	/**
	 * metodo que nos dice si estamos en un estado final
	 * @return true si es final, false en otro caso
	 */
	public boolean esFinal(){
		return (this.g4==2);
	}
	/**
	 * Metodo que genera todos los hijos del nodo actual
	 * @return vector con todos los nodos
	 */
	public Vector generaHijos(){
    	Vector nuevo=new Vector(0,1);
    	NodoGarrafas op1=this.llena3();
    	NodoGarrafas op2=this.llena4();
    	NodoGarrafas op3=this.vacia3();
    	NodoGarrafas op4=this.vacia4();
    	NodoGarrafas op5=this.vierte3();
    	NodoGarrafas op6=this.vierte4();
    	if (op1!=null) nuevo.addElement(op1);
        if (op2!=null) nuevo.addElement(op2);
      	if (op3!=null) nuevo.addElement(op3);
      	if (op4!=null) nuevo.addElement(op4);
      	if (op5!=null) nuevo.addElement(op5);
      	if (op6!=null) nuevo.addElement(op6);
        return nuevo;
	}

}
